package cn.promonkey.core.config;

import cn.promonkey.core.dto.UserDto;
import cn.promonkey.core.security.SecurityService;
import cn.promonkey.core.toolkit.UserInfoUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.buf.MessageBytes;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.util.*;

@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        String requestURI = httpServletRequest.getRequestURI();
        //非权限请求，直接通过
        if(requestURI.startsWith("/api")||requestURI.startsWith("/sso"))  {
        	return true;
        //异常请求处理	
        } else if (requestURI.equals("/error")) {
            Object a = findCoyoteRequest(httpServletRequest);
            Field coyoteRequest = a.getClass().getDeclaredField("coyoteRequest");
            coyoteRequest.setAccessible(true);
            Object b = coyoteRequest.get(a);

            Field uriMB = b.getClass().getDeclaredField("uriMB");
            uriMB.setAccessible(true);
            MessageBytes c = (MessageBytes) uriMB.get(b);
            System.out.println(c.getString());
            requestURI = c.getString();
        }
        UserDto user = SecurityService.getCurrentUserAndCheck(requestURI, HttpRequestHelper.getBodyString(httpServletRequest));
        if(null != user){
            UserInfoUtils.setUserInfo(user);
            return true;
        } else {
            // 不存在则跳转到登录页
            httpServletResponse.setStatus(401);
            return false;
        }
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) {
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        UserInfoUtils.removeUserInfo();
    }

    /**
     * @return java.lang.Class
     * @Author wultn
     * @Description 根据Field获得对应的Class
     * @Date 14:00 2020/2/28
     * @Param [classObject, name]
     **/
    private Class getClassByName(Class classObject, String name) {
        Map<Class, List<Field>> fieldMap = new HashMap<>();
        Class returnClass = null;
        Class tempClass = classObject;
        while (tempClass != null) {
            fieldMap.put(tempClass, Arrays.asList(tempClass.getDeclaredFields()));
            tempClass = tempClass.getSuperclass();
        }

        for (Map.Entry<Class, List<Field>> entry : fieldMap.entrySet()) {
            for (Field f : entry.getValue()) {
                if (f.getName().equals(name)) {
                    returnClass = entry.getKey();
                    break;
                }
            }
        }
        return returnClass;
    }

    /**
     * @return java.lang.Object
     * @Author wultn
     * @Description 递归遍历父类寻找coyoteRequest Field
     * @Date 14:01 2020/2/28
     * @Param [request]
     **/
    private Object findCoyoteRequest(Object request) throws Exception {
        Class a = getClassByName(request.getClass(), "request");
        Field request1 = a.getDeclaredField("request");
        request1.setAccessible(true);
        Object b = request1.get(request);
        if (getClassByName(b.getClass(), "coyoteRequest") == null) {
            return findCoyoteRequest(b);
        } else {
            return b;
        }
    }
    
}
